import os
import sys
import models
import widgets
import utils
#from StringIO import StringIO
#log = StringIO()

from django.utils import simplejson as json

base_path = os.path.abspath(os.path.dirname(__file__))
sys.path.append(base_path)


def _full_path(p):
    return os.path.join(base_path, p)

def _is_module(f):
    fname, ext = os.path.splitext(f)
    return os.path.isfile(_full_path(f)) and ext in ['.py', '.pyc', '.pyo'] and fname not in ['__init__', 'Base']

_is_pkg = lambda p:os.path.isdir(_full_path(p)) and os.path.exists(os.path.join(_full_path(p), '__init__.py'))
_get_module_name = lambda f: os.path.splitext(f)[0]


class WidgetBase(object):
    custom_data = ''

    def isenabled(self):
        entity = self.dbentity()
        if entity:
            return entity.enabled
        else:
            return False

    def fullname(self):
        return '.'.join([self.__module__,self.__class__.__name__])

    def order(self):
        entity = self.dbentity()
        if entity:
            return entity.order
        else:
            return 1

    def set_data(self, data):
        # i assume that u must enable it
        # in order to customize it.

        dbentity = self.enable()
        dbentity.order = utils.safeint(data.get('order'), 1)
        dbentity.data = json.dumps(data)
        dbentity.put()

    def get_data(self):
        data = None
        dbentity = self.dbentity()
        if dbentity and dbentity.data:
            data = json.loads(dbentity.data)
        return data

    def render(self):
        return ''

    def customize_form(self):
        return None

    def dbentity(self):
        return models.Widget.get_by_key_name(self.fullname())

    def enable(self):
        dbentity = self.dbentity()
        fullname = self.fullname()
        if not dbentity:
            dbentity = models.Widget(fullname=fullname,
                            data=models.db.Text(self.custom_data),# 'utf-8'),
                            enabled=True, key_name=fullname)
        else:
            dbentity.enabled = True
        dbentity.put()
        return dbentity

    def disable(self):
        dbentity = self.dbentity()
        if dbentity:
            dbentity.enabled = False
            dbentity.put()


def _is_widget(obj):
    if not obj:
        return False

    return (WidgetBase in obj.__class__.__bases__)

def myimport(path):
    module, func = path.rsplit('.', 1)
    mod = __import__(module, {}, {}, [''])
    return getattr(mod, func)

collection = {}

def get_widgets():
    names = os.listdir(base_path)
    modules_names = map(_get_module_name, filter(_is_module, names))
    modules_names.extend(filter(_is_pkg, names))

    for name in set(modules_names):
        #log.write('.'.join([os.path.basename(base_path), name]))
        __import__('.'.join([os.path.basename(base_path), name]))


    return collection.values()


def _widget_order(w, v):
    return cmp(w.order(), v.order())

def get_enabled_widgets():
    all = (w for w in get_widgets() if w.isenabled())
    return sorted(all, _widget_order)


def add_widget(widget):
    global collection
    if _is_widget(widget):
        collection[widget.fullname()] = widget


def get_widget_by_name(name):
    return collection.get(name, None)
